#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include <memory>

int add(int num1, int num2){
    std::cout << "into add..." << std::endl;
    return num1 + num2;
}

// std::async模板函数
void async_test(){
    // async异步调用函数
    // std::launch::async 异步调用策略 内部创建一个线程立即执行函数
    //std::future<int> res = std::async(std::launch::async, add, 11, 22);
    // std::launch::deferred 同步调用策略 获取结果的时候再次执行函数
    std::future<int> res = std::async(std::launch::deferred, add, 11, 22);
    std::this_thread::sleep_for(std::chrono::seconds(1));  
    std::cout << "=====================" << std::endl;
    std::cout << res.get() << std::endl;
}

// std::packaged_task模板类 对异步函数进行二次封装 封装成一个任务包
void packaged_test(){
    // 用智能指针来管理任务包
    auto task = std::make_shared<std::packaged_task<int(int, int)>>(add);
    // 获取任务包关联的future对象
    std::future<int> res = task->get_future();
  
    // 创建线程来执行任务包
    std::thread td([task](){
        (*task)(11, 22); 
    });

    // 获取结果
    std::cout << res.get() << std::endl;
    td.join();
}

// std::promise模板类 对异步任务结果进行封装
void promise_test(){
    // 先实例化一个指定结果的promise对象
    std::promise<int> pro;
    // 获取关联的future对象
    std::future<int> res = pro.get_future();
    // 创建线程执行异步函数
    std::thread td([&pro](){
        int sum = add(11, 22);
        pro.set_value(sum);
    });
    // 获取结果
    std::cout << res.get() << std::endl;
    td.join();
}

int main(){
    //packaged_test();
    promise_test();
    return 0;
}